use serde::{ser::SerializeStruct, Serialize};
use thiserror::Error;

#[derive(Debug, Error)]
pub enum DatabaseError {
    #[error("data store disconnected")]
    Disconnect,
    #[error("NOTFOUND")]
    NotFound {
        #[source]
        err: diesel::result::Error,
        message: String,
    },
    #[error("username {0} is not  exist!")]
    UserIsExist(String),
}
//*实现序列化
impl Serialize for DatabaseError {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: serde::Serializer,
    {
        match self {
            DatabaseError::Disconnect => {
                let mut state = serializer.serialize_struct("DatabaseError", 2)?;
                state.serialize_field("type", "Disconnect")?;
                state.serialize_field("message", "failed to connect")?;
                state.end()
            }
            DatabaseError::NotFound { err, message } => {
                let mut state = serializer.serialize_struct("DatabaseError", 3)?;
                state.serialize_field("type", "NotFound")?;
                state.serialize_field("message", &format!("user ${} not found!", message))?;
                state.serialize_field("error", &err.to_string())?;
                state.end()
            }
            DatabaseError::UserIsExist(_) => todo!(),
        }
    }
}

impl DatabaseError {
    pub fn not_found(message: impl AsRef<str>) -> Self {
        DatabaseError::NotFound {
            err: diesel::result::Error::from(diesel::result::Error::NotFound),
            message: message.as_ref().to_string(),
        }
    }
}
